<template>
  <div>
    <!-- <span @click="toggleMeasure">{{ title }}</span> -->
    <el-menu-item index="8-1" @click="toggleMeasure('LineString')">
      测量距离
    </el-menu-item>
    <el-menu-item index="8-2" @click="toggleMeasure('Polygon')">
      测量面积
    </el-menu-item>
    <el-menu-item index="8-3" @click="closeMeasure">关闭测量</el-menu-item>
  </div>
</template>

<script setup>
import { createDraw } from "../utils/createDraw";
let drawTypeMeasure = "";
let $map = null;
onMounted(() => {
  $map = inject("$map");
});
// 测量参数
let sketch; //当前要素
let helpTooltipElement; //帮助提示框元素
let helpTooltip; //帮助提示内容
let measureTooltipElement; // 测量提示元素
let measureTooltip; //测量值
let continuePolygonMsg = "单击此处绘制多边形"; //绘制面提示文字
let continueLineMsg = "单击此处绘制线"; //绘制线提示文字
let listener;

// 设置数据源、图层、画笔
let drawSourceMeasure = new ol.source.Vector({});
let drawLayerMeasure = new ol.layer.Vector({
  source: drawSourceMeasure,
  style: new ol.style.Style({
    //图层样式
    fill: new ol.style.Fill({
      color: "rgba(255, 255, 255, 0.3)", //填充颜色
    }),
    stroke: new ol.style.Stroke({
      color: "#0099ff", //边框颜色
      width: 3, // 边框宽度
    }),
    image: new ol.style.Circle({
      radius: 7,
      fill: new ol.style.Fill({
        color: "#0099ff",
      }),
    }),
  }),
});
let drawMeasure = null;
// 开始测量
const toggleMeasure = (measureType) => {
  // 清除之前的画笔
  if (drawMeasure) {
    $map.removeLayer(drawLayerMeasure);
    $map.removeInteraction(drawMeasure);
  }
  // 创建当前类型画笔
  drawTypeMeasure = measureType;
  drawMeasure = createDraw({
    type: drawTypeMeasure,
    source: drawSourceMeasure,
  });
  //   console.log(drawTypeMeasure);
  $map.addLayer(drawLayerMeasure);
  $map.addInteraction(drawMeasure);

  // 创建文字提示
  createTextPrompt();

  // 开始绘制
  drawMeasure.on(
    "drawstart",
    function (evt) {
      $map.addOverlay(helpTooltip);
      sketch = evt.feature;
      let tooltipCoord = evt.coordinate;
      // 获取测量值，设置到工具提示框
      listener = sketch.getGeometry().on("change", function (evt) {
        let geom = evt.target;
        let output;
        // 判断是线还是面
        if (geom instanceof ol.geom.Polygon) {
          output = formatArea(geom);
          tooltipCoord = geom.getInteriorPoint().getCoordinates();
        } else if (geom instanceof ol.geom.LineString) {
          output = formatLength(geom);
          tooltipCoord = geom.getLastCoordinate();
        }
        measureTooltipElement.innerHTML = output;
        measureTooltip.setPosition(tooltipCoord);
      });
    },
    this
  );
  // 绘制结束
  drawMeasure.on(
    "drawend",
    function () {
      measureTooltipElement.className = "ol-tooltip ol-tooltip-static";
      measureTooltip.setOffset([0, -7]);
      // 清空要素和提示框
      sketch = null;
      measureTooltipElement = null;
      // 创建展示结果
      createMeasureTooltip();
      ol.Observable.unByKey(listener);
      //   $map.removeOverlay(measureTooltip);
      $map.removeOverlay(helpTooltip);
    },
    this
  );
};
// 关闭测量
const closeMeasure = () => {
  $map.removeLayer(drawLayerMeasure);
  $map.removeInteraction(drawMeasure);
  drawSourceMeasure.clear();
  // 删除文字提示
  removeTextPrompt();
};

// 创建文字提示
const createTextPrompt = () => {
  // 创建文字提示元素
  createMeasureTooltip();
  createHelpTooltip();
  // 监听鼠标移动
  $map.on("pointermove", pointerMoveHandler);
  // 鼠标移出，隐藏样式
  $map.getViewport().addEventListener("mouseout", function () {
    helpTooltipElement.classList.add("hidden");
  });
};
//移除文字提示
const removeTextPrompt = () => {
  $map.un("pointermove", pointerMoveHandler);
  $map.getViewport().removeEventListener("mouseout", function () {
    helpTooltipElement.classList.add("hidden");
  });
  $map.removeOverlay(measureTooltip);
  $map.removeOverlay(helpTooltip);

  let textPrompt = document.querySelectorAll(
    ".ol-overlay-container.ol-selectable"
  );
  // console.log(textPrompt, 7878);
  for (let i = 0; i < textPrompt.length; i++) {
    const element = textPrompt[i];
    // console.log(element.firstChild, 1111);
    if (element.firstChild) {
      if (element.firstChild.className === "ol-tooltip ol-tooltip-static") {
        // console.log(element.firstChild, 2222);
        element.remove();
      }
    }
  }
};

// 鼠标移动函数，展示提示文字
const pointerMoveHandler = (evt) => {
  if (evt.dragging) {
    return;
  }
  let helpMsg = "点击开始绘制";
  if (sketch) {
    // 测量时的提示文字
    const geom = sketch.getGeometry();
    if (geom instanceof ol.geom.Polygon) {
      helpMsg = continuePolygonMsg;
    } else if (geom instanceof ol.geom.LineString) {
      helpMsg = continueLineMsg;
    }
  }
  // 设置提示对话框
  helpTooltipElement.innerHTML = helpMsg;
  helpTooltip.setPosition(evt.coordinate);
  helpTooltipElement.classList.remove("hidden");
};
// 创建测量提示元素
const createMeasureTooltip = () => {
  // 如已经有了则移除
  if (measureTooltipElement) {
    measureTooltipElement.parentNode.removeChild(measureTooltipElement);
  }
  // 创建div，new一个Overlay对象，div作为element的属性值
  measureTooltipElement = document.createElement("div");
  measureTooltipElement.className = "ol-tooltip ol-tooltip-measure";
  measureTooltip = new ol.Overlay({
    element: measureTooltipElement,
    offset: [0, -15],
    positioning: "bottom-center",
  });
  $map.addOverlay(measureTooltip);
};
// 创建帮助提示框元素
const createHelpTooltip = () => {
  if (helpTooltipElement) {
    helpTooltipElement.parentNode.removeChild(helpTooltipElement);
  }
  helpTooltipElement = document.createElement("div");
  helpTooltipElement.className = "ol-tooltip hidden";
  helpTooltip = new ol.Overlay({
    element: helpTooltipElement,
    offset: [15, 0],
    positioning: "center-left",
  });
  $map.addOverlay(helpTooltip);
};

// 面积测量函数
const formatArea = (polygon) => {
  let sphere = new ol.Sphere();
  let sourceProj = $map.getView().getProjection(); // 获取投影坐标系
  let area = sphere.getArea(polygon, {
    projection: sourceProj,
  });
  let output;
  if (area > 10000) {
    output = Math.round((area / 1000000) * 100) / 100 + " " + "km<sup>2</sup>";
  } else {
    output = Math.round(area * 100) / 100 + " " + "m<sup>2</sup>";
  }
  return output;
};

// 长度测量函数
const formatLength = (line) => {
  let sphere = new ol.Sphere();
  let sourceProj = $map.getView().getProjection(); // 获取投影坐标系
  let length = sphere.getLength(line, {
    projection: sourceProj,
  });
  let output;
  if (length > 100) {
    output = Math.round((length / 1000) * 100) / 100 + " " + "km";
  } else {
    output = Math.round(length * 100) / 100 + " " + "m";
  }
  return output;
};
</script>

<style lang="scss" scoped></style>
